<?php
/**
 * Base_App
 *
 * LICENSE
 *
 * This source file is subject to the new CC-GNU LGPL
 * It is available through the world-wide-web at this URL:
 * http://creativecommons.org/licenses/LGPL/2.1/
 *
 * @category   Base_App
 * @copyright  Copyright (c) 2009 Alexander fanatique* Thomas (me@alexander-thomas.net)
 * @license    http://creativecommons.org/licenses/LGPL/2.1/
 */

/**
 * Abstract class for running migrations (building the databse) 
 * @todo This implementation is MySQL only
 */
abstract class Base_App_Migrations{
    
    /**
     * @var Zend_Db_Adapter_Abstract
     */
	protected $_db;
	
	/**
	 * @var Array
	 */
	protected $_sql = array();
	
	/**
     * @var Array
     */
	protected $tables = array();
	
	/**
     * @var Array
     */
    protected $initial_content = array();
    
	/**
	 * Contructor calls all methods which are neede dto (re)build the database
	 * This creates a huge SQL statement which is executed by calling run()
	 * @param Zend_Db_Adapter_Abstract $db
	 * @param string $dbName
	 * @see run()
	 */
	function Base_App_Migrations(Zend_Db_Adapter_Abstract $db, $dbName){
		$this->_db = $db;
		$this->drop($dbName);
		$this->defineTables();
		$this->defineInitialContent();
	}
	
	/**
	 * Drops all tables of the current database
	 * @param string $dbName
	 */
	protected function drop($dbName){
		$tables = $this->_db->fetchAll('SHOW FULL TABLES;');
		foreach($tables AS $table){
			if($table['Table_type'] == 'VIEW'){
				$this->_sql[] = "DROP VIEW ".$table['Tables_in_'.$dbName].";\n";
			}else{
				$this->_sql[] = "DROP TABLE ".$table['Tables_in_'.$dbName].";\n";				
			}
		}
	}
	
	/**
	 * Executes the migration SQL statement
	 */
	public function run(){
		foreach($this->_sql AS $stmt){
			$this->_db->query($stmt);
		}
	}
	
	/**
	 * Getter for the SQL statement for debugging purposes
	 * @return string 
	 */
	public function getSql(){
		return implode("\n", $this->_sql);
	}

	/**
	 * Must be implemented with all tables that have to be created
	 * 
	 * @see $_tables
	 */
	abstract protected function defineTables();
	
	/**
	 * Must be oimplemented with initial content that has to be inserted into the databse 
	 * during setup of the application
	 * 
	 * @see $_initial_content
	 */
	abstract protected function defineInitialContent();
	
	/**
	 * Get defined table(s).
	 * 
	 * @param  String $table
	 * @return Array
	 */
	public function getTables($table = '')
	{
	    if(is_string($table) && isset($this->tables[$table]))
	    {
	        return $this->tables[$table];
	    }
	    
	    return $this->tables;
	}
	
    /**
     * Get initial data.
     * 
     * @param  String $table
     * @return Array
     */
    public function getInitialContent($table = '')
    {
        
    }
    
	/**
	 * Method for creating a table
	 * @param string $name
	 * @param array $fields
	 * @param string $primary
	 * @param array $keys
	 * @param array $uniqueKeys
	 * @param array $fulltextKeys
	 * @param string $engine (default: 'MyISAM')
	 * @param string $charset (default: 'utf8')
	 * @param string $collate
	 * @param  int $autoIncrement
	 */
	protected function createTable($name, array $fields, $primary, array $keys=array(), array $uniqueKeys = array(), array $fulltextKeys = array(), $engine='MyISAM', $charset='utf8', $collate, $autoIncrement=0){
		$sql = "CREATE TABLE " . $name . " (\n";
		foreach($fields AS $field){
			$sql .= $field['name'] . " " . $field['type'] . " " . $field['null'] . " ";
			if(!empty($field['extras'])) $sql .= $field['extras'];
			$sql .= ",\n";
		}

		$countKeys = count($keys);
		$countFulltextKeys = count($fulltextKeys);
		$countUniqueKeys = count($uniqueKeys);
		$sqlKeys = array();
		if(!empty($primary)){
			$sqlKeys[] = "PRIMARY KEY (" . $primary . ")";
		}
		
		for($i=0;$i<$countFulltextKeys;$i++){
			$sqlKeys[] = "FULLTEXT KEY " . $fulltextKeys[$i] . " (" . $fulltextKeys[$i] . ")";
		}
		
		for($i=0;$i<$countUniqueKeys;$i++){
			$sqlKeys[] = "UNIQUE KEY " . $uniqueKeys[$i] . " (" . $uniqueKeys[$i] . ")";
			//if($i < $countUniqueKeys - 1) $sql .= ",\n";
		}

		for($i=0;$i<$countKeys;$i++){
			$sqlKeys[] = "KEY " . str_replace(",",'_',$keys[$i]) . " (" . $keys[$i] . ")";
		}
		if(count($sqlKeys) > 0) $sql .= implode(',',$sqlKeys);
		else $sql = substr($sql, 0, strlen($sql)-2);

		$sql .= "\n) ENGINE=" . $engine . "  DEFAULT CHARSET=" . $charset . " COLLATE=" . $collate;
		if($autoIncrement > 0) $sql .= " AUTO_INCREMENT=" . $autoIncrement;
		$sql .= " ;\n";
		$this->_sql[] =  $sql;
	}
	
	/**
	 * Method for inserting data into a table
	 * @param string $table
	 * @param array $row
	 */
	protected function insert($table, array $row){
		$keys = array_keys($row);
		$values = array_values($row);
		$values = array_map(array($this->_db, 'quote'), $values);
		$this->_sql[] = "INSERT INTO " . $table . " (" . implode(',', $keys) . ") VALUES (" . implode(",", $values) . ");";
	}
}
?>
